package com.github.elliot.usercenter.service;

import com.github.elliot.domain.UserVO;
import com.github.elliot.usercenter.dao.PermissionRepository;
import com.github.elliot.usercenter.dao.UserRepository;
import com.github.elliot.usercenter.po.Permission;
import com.github.elliot.usercenter.po.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    public Flux<User> findAll() {
        return userRepository.findAll();
    }

    public Mono<User> findByUserNo(String userNo) {
        return userRepository.findByUserNo(userNo);
    }

    public Mono<UserVO> getUserByUsername(String username) {
        return userRepository.findUserByUsername(username)
                .flatMap(user -> permissionRepository.findPermissionListByUserNo(user.getUserNo())
                        .map(Permission::getBackendUrl)
                        .filter(Objects::nonNull)
                        .map(backendUrl -> Arrays.asList(backendUrl.split(",")))
                        .flatMap(Flux::fromIterable)
                        .collectList()
                        .map(permissions -> {
                            UserVO userVO = new UserVO();
                            BeanUtils.copyProperties(user, userVO);
                            userVO.setResourceList(permissions);
                            return userVO;
                        }))
                .timeout(Duration.ofSeconds(5))
                .onErrorResume(throwable -> {
                    log.error("获取用户详细信息失败 username:{}", username, throwable);
                    return Mono.just(new UserVO());
                });
    }

    public Mono<User> save(User user) {
        return userRepository.save(user);
    }

    @Transactional
    public Flux<User> saveUsers(List<User> userList) {
        return userRepository.saveAll(userList);
    }

    public Mono<Void> deleteByUserNo(String userNo) {
        return userRepository.updateByUserNo(userNo);
    }

    public Mono<Page<User>> pageListService(Integer current, Integer size) {
        List<Criteria> criteriaList = new ArrayList<>();
        criteriaList.add(Criteria.where("del_flag").is(0));
        return userRepository.pageList(criteriaList, current, size);
    }
}
